#include "camerafps.h"
#include "application.h"
#include "inputs/manager.h"
#include "physicsobject.h"


namespace infinity {


CameraFps::CameraFps()
{
	_angleX = _angleY = 0;
	m_cameraNode.setPosition(dw::maths::Point3f(0.0f, 1.0f, 0.0f));

	const dw::system::Window& window = Application::getInstance().getWindow();
	m_camera.setAspectRatio( (dw::float32)window.getWidth() / (dw::float32)window.getHeight() );

	m_mouseRotate.addCondition(dw::inputs::KeyStateCondition(OIS::KC_ESCAPE, dw::inputs::ButtonStateCondition::Up));
	m_mouseRotate.addSampler(dw::inputs::MouseCursorSampler(dw::inputs::MouseCursorSampler::X, dw::inputs::MouseCursorSampler::Relative));
	m_mouseRotate.addSampler(dw::inputs::MouseCursorSampler(dw::inputs::MouseCursorSampler::Y, dw::inputs::MouseCursorSampler::Relative));

	m_resetCamera.addCondition(dw::inputs::KeyStateCondition(OIS::KC_HOME, dw::inputs::ButtonStateCondition::Down));
}

CameraFps::~CameraFps()
{
	;
}


/*virtual*/ void CameraFps::update(dw::float32 deltaT)
{
	bool cameraNeedsFix = false;
	

	if(m_physicsObject !=NULL)
	{
		dw::maths::Point3f position(m_physicsObject->getTransform().pos.x,m_physicsObject->getTransform().pos.y + 1.0f,m_physicsObject->getTransform().pos.z);
		m_cameraNode.setPosition(position);
	}

	if(m_entity !=NULL && ((CharactereEntity*)m_entity)->getPhysiqueObject())
	{
		const Matrix4f matrix = m_entity->getMatrix();
		dw::maths::Point3f position(matrix.pos.x,matrix.pos.y + 1.0f,matrix.pos.z);
		m_cameraNode.setPosition(position);
	
		if (m_mouseRotate.isActive())
		{
			dw::float32 winSize = (dw::float32)Application::getInstance().getWindow().getHeight();
			dw::float32 valueX = 0.3f * m_mouseRotate.getValue(0) / winSize;
			dw::float32 valueY = 0.3f * m_mouseRotate.getValue(1) / winSize;

			_angleY += valueY;

			//fct min max ....
			if(_angleY > 0.45f)
				_angleY = 0.45f;

			if(_angleY < -0.45f )
				_angleY = -0.45f;

			const Matrix4f cameraMtx(m_cameraNode.getTransform());
			const dw::maths::Quaternionf cameraRotY = dw::maths::Quaternionf::fromAxisAngle(Vector3f::unitY,
				dw::maths::pi * -valueX);


			const dw::maths::Quaternionf cameraRotX = dw::maths::Quaternionf::fromAxisAngle(Vector3f::unitX,
				dw::maths::pi * _angleY);

			const dw::maths::Matrix3f rotationMtx = (cameraRotY + cameraRotX).toMatrix();

			m_cameraNode.setTransform(Matrix4f(rotationMtx, Vector3f::zero) * cameraMtx);

			// todo voir avec xav pour que les entity ai une matrice ... (node ou autre .... )
			physics::Object * obj = ((CharactereEntity*)m_entity)->getPhysiqueObject();
			const Matrix4f matrix = ((CharactereEntity*)m_entity)->getMatrix();
			obj->setTransform(Matrix4f(cameraRotY.toMatrix(), Vector3f::zero) * matrix);
		
			m_cameraNode.setTransform(Matrix4f(cameraRotX.toMatrix(), Vector3f::zero) * obj->getTransform());
		}

	}
}

/*virtual*/ void CameraFps::onRegistered()
{
	dw::inputs::InputManager& inputManager(dw::inputs::InputManager::getInstance());

	inputManager.registerCommand(&m_mouseRotate);
	inputManager.registerCommand(&m_resetCamera);
}

/*virtual*/ void CameraFps::onUnRegistered()
{
	dw::inputs::InputManager& inputManager(dw::inputs::InputManager::getInstance());

	inputManager.unregisterCommand(&m_mouseRotate);
	inputManager.unregisterCommand(&m_resetCamera);

}

void CameraFps::bindPhysicsObject(physics::Object* physicsObject)
{
	m_physicsObject = physicsObject;
}

void CameraFps::bindEntity(Entity3D* entity)
{
	m_entity = entity;
}



} // namespace infinity 